home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Camelot / Camelot 064 (1990-02)(Swedish User Group of Amiga)(SE)(PD)[WB].zip / Camelot 064 (1990-02)(Swedish User Group of Amiga)(SE)(PD)[WB].adf / Csh / execom.c < prev    next >
C/C++ Source or Header  |  1990-02-14  |  19KB  |  751 lines

  1. /*
  2.  * EXECOM.C
  3.  *
  4.  * Matthew Dillon, 10 August 1986
  5.  *    Finally re-written.
  6.  *
  7.  * Version 2.07M by Steve Drew 10-Sep-87
  8.  *
  9.  * Version 4.00A by Carlo Borreo & Cesare Dieni 13-Jan-90
  10.  *
  11.  */
  12.  
  13. #define F_EXACT 0
  14. #define F_ABBR  1
  15.  
  16. #define ST_COND   0x01
  17. #define ST_NORED  0x02
  18. #define ST_NOEXP  0x04
  19. #define ST_AV     0x08 /* delimit args within a variable */
  20.  
  21. int has_wild = 0;                 /* set if any arg has wild card */
  22.  
  23. struct COMMAND {
  24.     int (*func)();
  25.     short minargs;
  26.     short stat;
  27.     int val;
  28.     char *name;
  29. };
  30.  
  31. extern char *format_insert_string();
  32. extern char *mpush(), *exarg();
  33.  
  34. extern int do_basename(), do_tackon();
  35. extern int do_fltupper(), do_fltlower();
  36. extern int do_strleft(), do_strright(), do_strmid(), do_strlen();
  37. extern int do_fornum(), do_forline(), do_exec();
  38. extern int do_diskchange(), do_stack(), do_fault(), do_path(), do_pri();
  39. extern int do_rpn(), do_resident(), do_truerun(), do_aset(), do_howmany();
  40. extern int do_open(), do_close(), do_fileslist(), do_htype();
  41. extern int do_run(), do_number(), do_assign(), do_join();
  42. extern int do_quit(), do_set_var(), do_unset_var();
  43. extern int do_echo(), do_source(), do_mv(), do_addbuffers();
  44. extern int do_cd(), do_pwd(), do_rm(), do_mkdir(), do_history();
  45. extern int do_mem(), do_cat(), do_dir(), do_info(), do_inc();
  46. extern int do_foreach(), do_return(), do_if(), do_label(), do_goto();
  47. extern int do_input(), do_ver(), do_sleep(), do_help();
  48. extern int do_strhead(), do_strtail(), do_relabel();
  49. extern int do_copy(), do_date(), do_protect(), do_ps();
  50. extern int do_forever(), do_abortline(), do_strings(), do_touch();
  51. extern int do_window(), do_search(), do_filenote(), do_rxrec(), do_rxsend();
  52. char *push_cpy();
  53.  
  54. static struct COMMAND Command[] = {
  55. do_run,        0, ST_AV,    0,    "\001",   /* may call do_source */
  56. do_abortline,    0, 0,        0,    "abortline",
  57. do_addbuffers,    2, 0,        0,    "addbuffers",
  58. do_set_var,    0, 0, LEVEL_ALIAS,    "alias",  /* uses avline */
  59. do_aset,    1, 0,        0,    "aset",
  60. do_assign,    0, 0,        0,    "assign",
  61. do_basename,    2, 0,        0,    "basename",
  62. do_cat,        0, 0,        0,    "cat",
  63. do_cd,        0, 0,        0,    "cd",
  64. do_close,    0, 0,        0,    "close",
  65. do_copy,    1, 0,        0,    "copy",
  66. do_copy,    1, 0,        0,    "cp",
  67. do_date,    0, 0,        0,    "date",
  68. do_inc,        1, 0,        -1,    "dec",
  69. do_rm,        0, 0,        0,    "delete",
  70. do_dir,        0, ST_NOEXP,    0,    "dir",
  71. do_diskchange,    1, 0,        0,    "diskchange",
  72. do_echo,    0, 0,        0,    "echo", /* uses avline */
  73. do_if,        0, ST_COND,    1,    "else",
  74. do_if,        0, ST_COND,    2,    "endif",
  75. do_exec,    1, 0,        0,    "exec",
  76. do_fault,    1, 0,        0,    "fault",
  77. do_filenote,    2, 0,        0,    "filenote",
  78. do_fileslist,    0, 0,        0,    "flist",
  79. do_fltlower,    0, 0,        0,    "fltlower",
  80. do_fltupper,    0, 0,        0,    "fltupper",
  81. do_foreach,    3, ST_NORED,    0,    "foreach",
  82. do_forever,    1, ST_NORED,    0,    "forever",
  83. do_forline,    3, ST_NORED,    0,    "forline",
  84. do_fornum,    4, ST_NORED,    0,    "fornum",
  85. do_goto,    1, 0,        0,    "goto",
  86. do_help,    0, 0,        0,    "help",
  87. do_history,    0, 0,        0,    "history",
  88. do_howmany,    0, 0,        0,    "howmany",
  89. do_htype,    1, 0,        0,    "htype",
  90. do_if,        1, ST_COND|ST_NORED,0,    "if",
  91. do_inc,        1, 0,        1,    "inc",
  92. do_info,    0, 0,        0,    "info",
  93. do_input,    1, 0,        0,    "input",
  94. do_join,    2, 0,        1,    "join",
  95. do_label,    1, ST_COND,    0,    "label",
  96. do_dir,        0, ST_NOEXP,    0,    "ls",
  97. do_mkdir,    0, 0,        0,    "md",
  98. do_mem,        0, 0,        0,    "mem",
  99. do_mkdir,    0, 0,        0,    "mkdir",
  100. do_mv,        2, 0,        0,    "mv",
  101. do_open,    3, 0,        0,    "open",
  102. do_path,    0, 0,        0,    "path",
  103. do_pri,        2, 0,        0,    "pri",
  104. do_protect,    2, 0,        0,    "protect",
  105. do_ps,        0, 0,        0,    "ps",
  106. do_pwd,        0, 0,        0,    "pwd",
  107. do_quit,    0, ST_NORED,    0,    "quit",
  108. do_truerun,    1, ST_NORED,    1,    "rback",
  109. do_mv,        2, 0,        0,    "rename",
  110. do_relabel,    2, 0,        0,    "relabel",
  111. do_resident,    0, 0,        0,    "resident",
  112. do_return,    0, 0,        0,    "return",
  113. do_rm,        0, 0,        0,    "rm",
  114. do_rpn,        0, ST_NOEXP|ST_NORED,0,    "rpn",
  115. do_rxrec,    1, 0,        0,    "rxrec",
  116. do_rxsend,    2, 0,        0,    "rxsend",
  117. do_truerun,    1, ST_NORED,    0,    "run",
  118. do_search,    2, 0,        0,    "search",
  119. do_set_var,    0, ST_AV, LEVEL_SET,    "set",
  120. do_sleep,    0, 0,        0,    "sleep",
  121. do_source,    0, ST_NORED|ST_AV, 0,    "source", /* uses avline */
  122. do_stack,    0, 0,        0,    "stack",
  123. do_strhead,    3, 0,        0,    "strhead",
  124. do_strings,    1, 0,        0,    "strings",
  125. do_strleft,    3, 0,        0,    "strleft",
  126. do_strlen,    2, 0,        0,    "strlen",
  127. do_strmid,    3, 0,        0,    "strmid",
  128. do_strright,    3, 0,        0,    "strright",
  129. do_strtail,    3, 0,        0,    "strtail",
  130. do_tackon,    3, 0,        0,    "tackon",
  131. do_touch,    0, 0,        0,    "touch",
  132. do_cat,        0, 0,        0,    "type",
  133. do_unset_var,    0, 0, LEVEL_ALIAS,    "unalias",
  134. do_unset_var,    0, 0, LEVEL_SET  ,    "unset",
  135. do_ver,        0, 0,        0,    "version",
  136. do_window,    0, ST_NOEXP,    0,    "window",
  137. '\0',        0, 0,        0,    NULL
  138. };
  139.  
  140. static unsigned char elast;        /* last end delimeter */
  141. static char Cin_ispipe, Cout_ispipe;
  142.  
  143. exec_command(base)
  144. char *base;
  145. {
  146. register char *scr;
  147. char buf[32];
  148.  
  149. if (!H_stack) {
  150.     add_history(base);
  151.     sprintf(buf, "%d", H_tail_base + H_len);
  152.     set_var(LEVEL_SET, v_histnum, buf);
  153.     }
  154. scr = malloc((strlen(base) << 2) + 2);
  155. preformat(base, scr);
  156. return (fcomm(scr, 1) ? -1 : 1);
  157. }
  158.  
  159. isalphanum(c)
  160. register char c;
  161. {
  162. return (
  163.     (c >= '0' && c <= '9') ||
  164.     (c >= 'a' && c <= 'z') ||
  165.     (c >= 'A' && c <= 'Z') ||
  166.     (c == '_')
  167.     );
  168. }
  169.  
  170. preformat(s, d)
  171. register char *s, *d;
  172. {
  173. register int si, di, qm;
  174.  
  175. si = di = qm = 0;
  176. while (s[si] == ' ' || s[si] == 9) ++si;
  177. while (s[si]) {
  178.     if (qm && s[si] != '\"' && s[si] != '\\') {
  179.         d[di++] = s[si++] | 0x80;
  180.         continue;
  181.         }
  182.     switch (s[si]) {
  183.         case ' ':
  184.         case 9:
  185.             d[di++] = ' ';
  186.             while (s[si] == ' ' || s[si] == 9) ++si;
  187.             if (s[si] == 0 || s[si] == '|' || s[si] == ';') --di;
  188.             break;
  189.         case '*':
  190.         case '?':
  191.             d[di++] = 0x80;
  192.         case '!':
  193.             d[di++] = s[si++];
  194.             break;
  195.         case '#':
  196.             d[di++] = '\0';
  197.             while (s[si]) ++si;
  198.             break;
  199.         case ';':
  200.         case '|':
  201.             d[di++] = s[si++];
  202.             while (s[si] == ' ' || s[si] == 9) ++si;
  203.             break;
  204.         case '\\':
  205.             d[di++] = s[++si] | 0x80;
  206.             if (s[si]) ++si;
  207.             break;
  208.         case '\"':
  209.             qm = 1 - qm;
  210.             ++si;
  211.             break;
  212.         case '^':
  213.             d[di++] = s[++si] & 0x1F;
  214.             if (s[si]) ++si;
  215.             break;
  216.         case '$': /* search end of var name and place false space */
  217.             d[di++] = 0x80;
  218.             d[di++] = s[si++];
  219.             while (isalphanum(s[si])) d[di++] = s[si++];
  220.             d[di++] = 0x80;
  221.             break;
  222.         default:
  223.             d[di++] = s[si++];
  224.             break;
  225.         }
  226.     }
  227. d[di++]=0;
  228. d[di]=0;
  229. if (debug) fprintf (stderr,"PREFORMAT: %d :%s:\n", strlen(d), d);
  230. }
  231.  
  232. extern BPTR extOpen();
  233.  
  234. /*
  235.  * process formatted string.  ' ' is the delimeter.
  236.  *
  237.  *    0: check '\0': no more, stop, done.
  238.  *    1: check $.     if so, extract, format, insert
  239.  *    2: check alias. if so, extract, format, insert. goto 1
  240.  *    3: check history or substitution, extract, format, insert. goto 1
  241.  *
  242.  *    4: assume first element now internal or disk based command.
  243.  *
  244.  *    5: extract each ' ' or 0x80 delimited argument and process, placing
  245.  *       in av[] list (except 0x80 args appended).  check in order:
  246.  *
  247.  *             '$'         insert string straight
  248.  *             '>'         setup stdout
  249.  *             '>>'        setup stdout flag for append
  250.  *             '<'         setup stdin
  251.  *             '*' or '?'  do directory search and insert as separate args.
  252.  *
  253.  *             ';' 0 '|'   end of command.  if '|' setup stdout
  254.  *                          -execute command, fix stdin and out (|) sets
  255.  *                           up stdin for next guy.
  256.  */
  257.  
  258.  
  259. fcomm(str, freeok)
  260. register char *str;
  261. {
  262.    static int alias_count;
  263.    int p_alias_count = 0;
  264.    char *istr;
  265.    char *nextstr;
  266.    char *command;
  267.    char *pend_alias = NULL;
  268.    char err = 0;
  269.    has_wild = 0;
  270.  
  271.    ++alias_count;
  272.  
  273.    mpush_base();
  274.    if (*str == 0)
  275.       goto done1;
  276. step1:
  277.    if (alias_count == MAXALIAS || ++p_alias_count == MAXALIAS) {
  278.       fprintf(stderr,"Alias Loop\n");
  279.       err = 20;
  280.       goto done1;
  281.    }
  282. /*
  283.    if (str[1] == '$') {
  284.       if (istr = get_var (LEVEL_SET, str + 2))
  285.          str = format_insert_string(str, istr, &freeok);
  286.    }
  287. */
  288.    istr = NULL;
  289.    if (*(unsigned char *)str < 0x80)
  290.       istr = get_var (LEVEL_ALIAS, str);  /* only if not \command */
  291.    *str &= 0x7F;                          /* remove \ teltail     */
  292.    if (istr) {
  293.       if (*istr == '%') {
  294.          pend_alias = istr;
  295.       } else {
  296.          str = format_insert_string(str, istr, &freeok);
  297.          goto step1;
  298.       }
  299.    }
  300.    if (*str == '!') {
  301.       char *p, c;                     /* fix to allow !cmd1;!cmd2 */
  302.       for(p = str; *p && *p != ';' ; ++p);
  303.       c = *p;
  304.       *p = '\0';
  305.       istr = get_history(str);
  306.       *p = c;
  307.       replace_head(istr);
  308.       str = format_insert_string(str, istr, &freeok);
  309.       goto step1;
  310.    }
  311.    nextstr = str;
  312.    command = exarg(&nextstr);
  313.    if (*command == 0)
  314.       goto done0;
  315.    if (pend_alias == 0) {
  316.       if (cmd_stat(command) & ST_COND)
  317.          goto skipgood;
  318.    }
  319.    if (disable || forward_goto) {
  320.       while (elast && elast != ';' && elast != '|')
  321.          exarg(&nextstr);
  322.       goto done0;
  323.    }
  324. skipgood:
  325.    {
  326.       register char *arg, *ptr, *scr;
  327.       short redir;
  328.       short doexpand;
  329.       short cont;
  330.       short inc;
  331.  
  332.       ac = 1;
  333.       av[0] = command;
  334. step5:                                          /* ac = nextac */
  335.       if (!elast || elast == ';' || elast == '|')
  336.          goto stepdone;
  337.  
  338.       av[ac] = '\0';
  339.       cont = 1;
  340.       doexpand = redir = inc = 0;
  341.  
  342.       while (cont && elast) {
  343.          int cstat = cmd_stat(command);
  344.  
  345.          ptr = exarg(&nextstr);
  346.          inc = 1;
  347.          arg = "";
  348.          cont = (elast == 0x80);
  349.          switch (*ptr) {
  350.          case '<':
  351.             redir = -2;
  352.          case '>':
  353.             if (cstat & (ST_NORED | ST_COND)) {
  354.                                                         /* don't extract   */
  355.                 redir = 0;                              /* <> stuff if its */
  356.                 arg = ptr;                              /* external cmd.   */
  357.                 break;
  358.             }
  359.             ++redir;
  360.             arg = ptr + 1;
  361.             if (*arg == '>') {
  362.                redir = 2;        /* append >> */
  363.                ++arg;
  364.             }
  365.             cont = 1;
  366.             break;
  367.          case '$':
  368.             /* restore args if from set command or pend_alias */
  369.             if ((arg = get_var(LEVEL_SET, ptr + 1)) != NULL) {
  370.                if (cstat & ST_COND) {
  371.                   char *tp;
  372.                   tp = push_cpy(arg);
  373.                   arg = tp;
  374.                }
  375.                else {
  376.                   char *pe, sv;
  377.                   while (pe = index(arg,0xA0)) {
  378.                      sv = *pe;
  379.                      *pe = '\0';
  380.                      av[ac++] = push_cpy(arg);
  381.                      *pe = sv;
  382.                      av[ac] = '\0';
  383.                      arg = pe+1;
  384.                   }
  385.                }
  386.             }
  387.             else
  388.                arg = ptr;
  389.             break;
  390.          case '*':
  391.          case '?':
  392.             if ((cstat & ST_NOEXP) == 0)
  393.                doexpand = 1;
  394.             arg = ptr;
  395.             break;
  396.          default:
  397.             arg = ptr;
  398.             break;
  399.          }
  400.  
  401.          /* Append arg to av[ac] */
  402.  
  403.          for (scr = arg; *scr; ++scr)
  404.             *scr &= 0x7F;
  405.          if (av[ac]) {
  406.             register char *old = av[ac];
  407.             av[ac] = mpush(strlen(arg)+strlen(av[ac]));
  408.             strcpy(av[ac], old);
  409.             strcat(av[ac], arg);
  410.          } else {
  411.             av[ac] = push_cpy(arg);
  412.          }
  413.          if (elast != 0x80)
  414.             break;
  415.       }
  416.  
  417.       /* process expansion */
  418.  
  419.       if (doexpand) {
  420.          char **eav, **ebase;
  421.          int eac;
  422.          has_wild = 1;
  423.          eav = ebase = expand(av[ac], &eac);
  424.          inc = 0;
  425.          if (eav) {
  426.             if (ac + eac + 2 > MAXAV) {
  427.                ierror (NULL, 506);
  428.                err = 1;
  429.             } else {
  430.                QuickSort(eav, eac);
  431.                for (; eac; --eac, ++eav)
  432.                   av[ac++] = push_cpy(*eav);
  433.             }
  434.             free_expand (ebase);
  435.          }
  436.       }
  437.  
  438.       /* process redirection  */
  439.  
  440.       if (redir && !err) {
  441.          register char *file = (doexpand) ? av[--ac] : av[ac];
  442.  
  443.          if (redir < 0)
  444.             Cin_name = file;
  445.          else {
  446.             Cout_name = file;
  447.             Cout_append = (redir == 2);
  448.          }
  449.          inc = 0;
  450.       }
  451.  
  452.       /* check elast for space */
  453.  
  454.       if (inc) {
  455.          ++ac;
  456.          if (ac + 2 > MAXAV) {
  457.             ierror (NULL, 506);
  458.             err = 1;                /* error condition */
  459.             elast = 0;              /* don't process any more arguemnts */
  460.          }
  461.       }
  462.       if (elast == ' ')
  463.          goto step5;
  464.    }
  465. stepdone:
  466.    av[ac] = '\0';
  467.  
  468.    /* process pipes via files */
  469.  
  470.    if (elast == '|' && !err) {
  471.       static int which;             /* 0 or 1 in case of multiple pipes */
  472.       which = 1 - which;
  473.       Cout_name = (which) ? Pipe1 : Pipe2;
  474.       Cout_ispipe = 1;
  475.    }
  476.  
  477.  
  478.    if (err)
  479.       goto done0;
  480.  
  481.    {
  482.       register int i;
  483.       char save_elast;
  484.       char *compile_av();
  485.       register char *avline;
  486.       unsigned char delim = ' ';
  487.  
  488.       save_elast = elast;
  489.       if (pend_alias || (cmd_stat(command) & ST_AV))
  490.          delim = 0xA0;
  491.       avline = compile_av(av,((pend_alias) ? 1 : 0), ac, delim, 0);
  492.  
  493.       if (pend_alias) {                               /* special % alias */
  494.          register char *ptr, *scr;
  495.          for (ptr = pend_alias; *ptr && *ptr != ' '; ++ptr);
  496.          set_var (LEVEL_SET, pend_alias + 1, avline);
  497.          free (avline);
  498.  
  499.          scr = malloc((strlen(ptr) << 2) + 2);
  500.          preformat (ptr, scr);
  501.          fcomm (scr, 1);
  502.          unset_var (LEVEL_SET, pend_alias + 1);
  503.       } else {                                        /* normal command  */
  504.          register int ccno;
  505.          long  oldcin  = Myprocess->pr_CIS;
  506.          long  oldcout = Myprocess->pr_COS;
  507.          char *Cin_buf;
  508.          struct FileHandle *ci;
  509.          long oldbuf;
  510.  
  511.          fflush(stdout);
  512.          ccno = find_command (command);
  513.          if ((Command[ccno].stat & (ST_NORED | ST_COND)) == 0) {
  514.             if (Cin_name) {
  515.                if ((Cin = (long)extOpen(Cin_name,1005L)) == 0L) {
  516.                   ierror (NULL, 504);
  517.                   err = 1;
  518.                   Cin_name = '\0';
  519.                } else {
  520.                   Myprocess->pr_CIS = _devtab[stdin->_unit].fd = Cin;
  521.                   ci = (struct FileHandle *)(((long)Cin)<<2);
  522.                   Cin_buf = (char *)AllocMem(202L, MEMF_PUBLIC);
  523.                   oldbuf = ci->fh_Buf;
  524.                   if (ci->fh_Buf == 0) /* fexec expects a CIS buffer */
  525.                      ci->fh_Buf = (long)Cin_buf>>2;
  526.                }
  527.             }
  528.             if (Cout_name) {
  529.                if (Cout_append && (Cout =(long)extOpen(Cout_name, 1005L)) ) {
  530.                      Seek(Cout, 0L, 1L);
  531.                } else {
  532.                   Cout = (long)extOpen(Cout_name,1006L);
  533.                }
  534.                if (Cout == NULL) {
  535.                   err = 1;
  536.                   ierror (NULL, 504);
  537.                   Cout_name = '\0';
  538.                   Cout_append = 0;
  539.                } else {
  540.                   Myprocess->pr_COS = _devtab[stdout->_unit].fd = Cout;
  541.                }
  542.             }
  543.          }
  544.          if (ac < Command[ccno].minargs + 1) {
  545.             ierror (NULL, 500);
  546.             err = -1;
  547.          } else if (!err) {
  548.             i = (*Command[ccno].func)(avline, Command[ccno].val);
  549.             if (i < 0)
  550.                i = 20;
  551.             err = i;
  552.          }
  553.          free (avline);
  554.          if (E_stack == 0 && Lastresult != err) {
  555.             Lastresult = err;
  556.             seterr();
  557.          }
  558.          if ((Command[ccno].stat & (ST_NORED | ST_COND)) == 0) {
  559.             if (Cin_name) {
  560.                fflush(stdin);
  561.                clearerr(stdin);
  562.                ci->fh_Buf = oldbuf;
  563.                extClose(Cin);
  564.                FreeMem(Cin_buf, 202L);
  565.             }
  566.             if (Cout_name) {
  567.                fflush(stdout);
  568.                clearerr(stdout);
  569.                stdout->_flags &= ~_DIRTY;    /* because of nil: device */
  570.                extClose(Cout);
  571.                Cout_append = 0;
  572.             }
  573.          }
  574.          Myprocess->pr_CIS =  _devtab[stdin->_unit].fd  = oldcin;
  575.          Myprocess->pr_COS =  _devtab[stdout->_unit].fd = oldcout;
  576.       }
  577.  
  578.       if (Cin_ispipe && Cin_name)
  579.          DeleteFile(Cin_name);
  580.       if (Cout_ispipe) {
  581.          Cin_name = Cout_name;         /* ok to assign.. static name */
  582.          Cin_ispipe = 1;
  583.       } else {
  584.          Cin_name = '\0';
  585.       }
  586.       Cout_name = '\0';
  587.       Cout_ispipe = 0;
  588.       elast = save_elast;
  589.    }
  590.    mpop_tobase();                      /* free arguments   */
  591.    mpush_base();                       /* push dummy base  */
  592.  
  593. done0:
  594.    {
  595.       char *str;
  596.       if (err && E_stack == 0) {
  597.          str = get_var(LEVEL_SET, v_except);
  598.          if (err >= ((str)?atoi(str):1)) {
  599.             if (str) {
  600.                ++H_stack;
  601.                ++E_stack;
  602.                exec_command(str);
  603.                --E_stack;
  604.                --H_stack;
  605.             } else {
  606.                Exec_abortline = 1;
  607.             }
  608.          }
  609.       }
  610.       if (elast != 0 && Exec_abortline == 0)
  611.          err = fcomm(nextstr, 0);
  612.       Exec_abortline = 0;
  613.       if (Cin_name)
  614.          DeleteFile(Cin_name);
  615.       Cin_name = NULL;
  616.       Cin_ispipe = 0;
  617.    }
  618. done1:
  619.    mpop_tobase();
  620.    if (freeok)
  621.       free(str);
  622.    --alias_count;
  623.    return ((int)err);                  /* TRUE = error occured    */
  624. }
  625.  
  626.  
  627. char *
  628. exarg(ptr)
  629. unsigned char **ptr;
  630. {
  631.    register unsigned char *end;
  632.    register unsigned char *start;
  633.  
  634.    start = end = *ptr;
  635.    while (*end && *end != 0x80 && *end != ';' && *end != '|' && *end != ' ')
  636.       ++end;
  637.    elast = *end;
  638.    *end = '\0';
  639.    *ptr = end + 1;
  640.    return ((char *)start);
  641. }
  642.  
  643. static char **Mlist;
  644.  
  645. mpush_base()
  646. {
  647.    char *str;
  648.  
  649.    str = malloc(5);
  650.    *(char ***)str = Mlist;
  651.    str[4] = 0;
  652.    Mlist = (char **)str;
  653. }
  654.  
  655. char *
  656. mpush(bytes)
  657. {
  658.    char *str;
  659.  
  660.    str = malloc(6 + bytes + 2);   /* may need extra 2 bytes in do_run() */
  661.    *(char ***)str = Mlist;
  662.    str[4] = 1;
  663.    Mlist = (char **)str;
  664.    return (str + 5);
  665. }
  666.  
  667. mpop_tobase()
  668. {
  669.    register char *next;
  670.    while (Mlist) {
  671.       next = *Mlist;
  672.       if (((char *)Mlist)[4] == 0) {
  673.          free (Mlist);
  674.          Mlist = (char **)next;
  675.          break;
  676.       }
  677.       free (Mlist);
  678.       Mlist = (char **)next;
  679.    }
  680. }
  681.  
  682.  
  683. /*
  684.  * Insert 'from' string in front of 'str' while deleting the
  685.  * first entry in 'str'.  if freeok is set, then 'str' will be
  686.  * free'd
  687.  */
  688.  
  689. char *format_insert_string(str, from, freeok)
  690. char *str;
  691. char *from;
  692. int *freeok;
  693. {
  694. register char *new1, *new2;
  695. register unsigned char *strskip;
  696. int len;
  697.  
  698. for (strskip = (unsigned char *)str;
  699.         *strskip && *strskip != ' ' 
  700.         && *strskip != ';' && *strskip != '|'
  701.         && *strskip != 0x80; ++strskip);
  702. len = strlen(from);
  703. new1 = malloc((len << 2) + 2);
  704. preformat(from, new1);
  705. len = strlen(new1) + strlen(strskip);
  706. new2 = malloc(len+2);
  707. strcpy(new2, new1);
  708. strcat(new2, strskip);
  709. new2[len+1] = 0;
  710. free (new1);
  711. if (*freeok) free (str);
  712. *freeok = 1;
  713. return new2;
  714. }
  715.  
  716. cmd_stat(str)
  717. char *str;
  718. {
  719. return(Command[find_command(str)].stat);
  720. }
  721.  
  722. find_command(str)
  723. char *str;
  724. {
  725. register unsigned short i;
  726. int len = strlen(str);
  727.  
  728. for (i = 0; Command[i].func; ++i)
  729.     if ( ! strncmp(str, Command[i].name, len)) return (int)i;
  730. return 0;
  731. }
  732.  
  733. do_help()
  734. {
  735. register struct COMMAND *com;
  736. int i=0;
  737.  
  738. for (com = &Command[1]; com->func; ++com) {
  739.     printf ("%-12s", com->name);
  740.     if (++i % 6 == 0) printf("\n");
  741.     }
  742. printf("\n");
  743. return 0;
  744. }
  745.  
  746. char *push_cpy(s)
  747. char *s;
  748. {
  749. return strcpy(mpush(strlen(s)), s);
  750. }
  751.